package com.example.chessbattleplatform.web.chess_rooms.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.chessbattleplatform.Pojo.Exception.BusinessException;
import com.example.chessbattleplatform.Pojo.Exception.StatusCode;
import com.example.chessbattleplatform.utils.GetLocalDateTimeUtils;
import com.example.chessbattleplatform.web.Sys_User.Pojo.mapper.User;
import com.example.chessbattleplatform.web.Sys_User.dataService.impl.UserDataServiceInterface;
import com.example.chessbattleplatform.web.chess_rooms.CopyUtils.CopyRoomsMapper;
import com.example.chessbattleplatform.web.chess_rooms.Pojo.Enum.RoomTypeEnum;
import com.example.chessbattleplatform.web.chess_rooms.Pojo.Enum.RoomUserColorEnum;
import com.example.chessbattleplatform.web.chess_rooms.Pojo.Enum.RoomUserEnum;
import com.example.chessbattleplatform.web.chess_rooms.Pojo.Enum.UpdateCategory;
import com.example.chessbattleplatform.web.chess_rooms.Pojo.Vo.*;
import com.example.chessbattleplatform.web.chess_rooms.Pojo.dto.RoomsDto;
import com.example.chessbattleplatform.web.chess_rooms.Pojo.mappers.RoomMember;
import com.example.chessbattleplatform.web.chess_rooms.Pojo.mappers.Rooms;
import com.example.chessbattleplatform.web.chess_rooms.dataService.impl.RoomMemberDataServiceInterface;
import com.example.chessbattleplatform.web.chess_rooms.dataService.impl.RoomsDataServiceInterface;
import com.example.chessbattleplatform.web.chess_rooms.service.impl.RoomsServiceInterface;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.UUID;

@Slf4j
@Service
@RequiredArgsConstructor
public class RoomsService implements RoomsServiceInterface {

    private final RoomsDataServiceInterface roomsDataServiceInterface;
    private final RoomMemberDataServiceInterface roomMemberDataServiceInterface;
    private final UserDataServiceInterface userDataServiceinterface;

    private final CopyRoomsMapper copyRoomsMapper;

    //创建房间
    @Transactional
    @Override
    @CacheEvict(value = "RoomService", key = "#userId")
    public UpdateRoomVo createRoom(RoomsDto roomsDto, Long userId) {
        // 玩家离开等待房间 会自动判断房间是否有玩家
        leaveRoom(userId);

        // 生成房间的 uuid
        String uuid = UUID.randomUUID().toString();

        Rooms rooms = copyRoomsMapper.RoomsDtoToRooms(roomsDto, uuid);

        //创建等待房间
        roomsDataServiceInterface.createRoom(rooms);

        //玩家加入等待房间
        AddPlayersWaitingRoom(uuid, userId);

        return UpdateRoomVo.builder()
                .category(UpdateCategory.ADD_DATA)
                .roomUuid(uuid)
                .name(roomsDto.getName())
                .UpdateDate(GetLocalDateTimeUtils.GetLocalDateTimeToStrings())
                .build();
    }

    // 列表查询
    @Override
    public RoomsLimitVo listRooms(Long current, Long limit) {
        // 分页查询
        Page<Rooms> allProductsKind = roomsDataServiceInterface.getAllProductsKind(current, limit);

        // 获取查询结果
        List<Rooms> records = allProductsKind.getRecords();


        // 转换类型
        List<RoomsVo> uploadFileVos = copyRoomsMapper.listToRoomMemberToRoomsLimitVo(records);

        // 获取房间人数
        uploadFileVos.forEach(e -> {
            e.setRoomPeopleNumber(roomMemberDataServiceInterface.CountNumberRoomMembers(e.getRoomUuid()));
        });

        //productPage.getPages() 总页码数
        //productPage.getSize() 每页显示的商品数量
        //productPage.getCurrent() 当前页码
        return new RoomsLimitVo(uploadFileVos, allProductsKind.getPages(), allProductsKind.getCurrent(), allProductsKind.getSize());
    }


    @Override
    public RoomsDataVo getRoom(Long userId) {
        // 查询当前用户信息
        RoomMember currentUserData = roomMemberDataServiceInterface.getUserRoomMember(userId);

        // 查询房间号
        String roomUuid = currentUserData.getRoomUuid();

        if (Objects.isNull(roomUuid) || roomUuid.isEmpty()) {
            throw new BusinessException(StatusCode.NOT_FOUND, "用户不存在");
        }

        //查询房间所有用户信息
        List<RoomMember> userRoomMember = roomMemberDataServiceInterface.getListUserRoomMember(roomUuid);

        // 获取玩家信息
        List<RoomUserData> PlayerInformation = copyRoomsMapper.listRoomMemberToRoomUserData(
                userRoomMember.stream()
                        .filter(e -> !e.getMemberType().equals(RoomUserEnum.SPECTATOR))
                        .toList()
        );

        // 获取观战者信息
        List<RoomUserData> Spectators = copyRoomsMapper.listRoomMemberToRoomUserData(
                userRoomMember.stream()
                        .filter(e -> e.getMemberType().equals(RoomUserEnum.SPECTATOR))
                        .toList()
        );

        //将 List<RoomMember> 转为 List<RoomUserData>
        List<RoomUserData> roomUserData = copyRoomsMapper.listRoomMemberToRoomUserData(userRoomMember);

        //查询 房间数据
        Rooms room = roomsDataServiceInterface.getRoom(roomUuid);

        //封装房间用户数据
        //Rooms -> RoomsDataVo
        RoomsDataVo roomsDataVo = copyRoomsMapper.RoomsToRoomsDataVo(room);

        //添加房间信息
        roomsDataVo.setRoomAllPlayerInformation(PlayerInformation);
        roomsDataVo.setRoomAudienceInformation(Spectators);
        //添加当前用户信息
        roomsDataVo.setCurrentUserData(copyRoomsMapper.RoomMemberToRoomUserData(currentUserData));
        return roomsDataVo;
    }

    //删除等待房间数据
    @Transactional
    @CacheEvict(value = "RoomService", allEntries = true)
    public UpdateRoomVo deleteTheWaitingRoomData(String roomId, Long userId) {
        //查询是否为房主
        if (!roomMemberDataServiceInterface.ToDetermineWhetherYouAreTheHomeowner(userId)) {
            throw new BusinessException(StatusCode.PERMISSIONS_INSUFFICIENT, "删除等待房间的权限不够");
        }

        if (roomsDataServiceInterface.IsMyRoom(roomId)) {
            if (!roomsDataServiceInterface.deleteWaitingRoom(roomId)) {
                throw new BusinessException(StatusCode.ERROR_CODE, "删除等待房间失败");
            }
            if (!roomMemberDataServiceInterface.quitAndCloseRoom(roomId)) {
                throw new BusinessException(StatusCode.ERROR_CODE, "删除等待房间失败");
            }
        }

        return UpdateRoomVo.builder()
                .category(UpdateCategory.DELETION_DATA)
                .roomUuid(roomId)
                .UpdateDate(GetLocalDateTimeUtils.GetLocalDateTimeToStrings())
                .build();
    }

    // 玩家加入等待房间
    @Override
    @Transactional
    @Cacheable(cacheNames = "RoomService", key = "#userId")
    public UpdateRoomVo joinRoom(String roomId, Long userId, String password) {

        // 判断玩家是否在指定等待房间内
        if (roomMemberDataServiceInterface.IsWhetherPlayerWaitingRoom(roomId, userId)) {
            return UpdateRoomVo.builder()
                    .category(UpdateCategory.NO_CHANGE)
                    .roomUuid(roomId)
                    .UpdateDate(GetLocalDateTimeUtils.GetLocalDateTimeToStrings())
                    .build();
        }

        // 判断玩家是否在其他等待房间内 如果存在会将玩家离开等待房间
        leaveRoom(userId);

        // 检查房间是否存在
        if (!roomsDataServiceInterface.IsMyRoom(roomId)) {
            throw new BusinessException(StatusCode.NOT_FOUND, "房间不存在");
        }

        // 检查房间密码
        if (roomsDataServiceInterface.IsRoomTypeEnum(roomId, RoomTypeEnum.PRIVATE) && !roomsDataServiceInterface.IsMyRoomPassword(roomId, password)) {
            // 房间 为 私密 密码不正确
            throw new BusinessException(StatusCode.MISSING_PARAMETER, "房间密码不正确");
        }

        // 房间 为 公开 不需要验证 与 房间 私密 密码 正确
        // 添加玩家到等待房间
        AddPlayersWaitingRoom(roomId, userId);


        return UpdateRoomVo.builder()
                .category(UpdateCategory.ADD_DATA)
                .roomUuid(roomId)
                .UpdateDate(GetLocalDateTimeUtils.GetLocalDateTimeToStrings())
                .build();

    }

    // 玩家离开房间
    @Override
    @Transactional
    @CacheEvict(value = "RoomService", key = "#userId")
    public UpdateRoomVo leaveRoom(Long userId) {

        // 查询房间号
        RoomMember userRoomMember = roomMemberDataServiceInterface.getUserRoomMember(userId);
        if (Objects.isNull(userRoomMember)) {
            return UpdateRoomVo.builder()
                    .category(UpdateCategory.NO_CHANGE)
                    .UpdateDate(GetLocalDateTimeUtils.GetLocalDateTimeToStrings())
                    .build();
        }

        String roomUuid = userRoomMember.getRoomUuid();

        //获取房间人数
        if (roomMemberDataServiceInterface.CountNumberRoomMembers(roomUuid) <= 1) {
            //直接删除 房间 和 房间成员
            return deleteTheWaitingRoomData(roomUuid, userId);
        }

        //查询是否为房主
        Boolean isHomeowner = roomMemberDataServiceInterface.ToDetermineWhetherYouAreTheHomeowner(userId);

        // 删除 房间成员
        if (!roomMemberDataServiceInterface.leaveRoom(userId)) {
            throw new BusinessException(StatusCode.ERROR_CODE, "玩家退出失败，请联系客服！");
        }

        //查询是否为房主
        if (isHomeowner) {
            // 更改房主
            List<RoomMember> listUserRoomMember = roomMemberDataServiceInterface.getListUserRoomMember(roomUuid);
            listUserRoomMember.remove(userRoomMember);


            RoomMember roomMember = listUserRoomMember.get(0);
            log.info("更改房主 {}", roomMember);
            roomMember.setMemberType(RoomUserEnum.ROOM_OWNER);
            if (!roomMemberDataServiceInterface.updateRoomMember(roomMember)) {
                throw new BusinessException(StatusCode.ERROR_CODE, "离开等待房间失败，请联系客服！");
            }
        }

        return UpdateRoomVo.builder()
                .category(UpdateCategory.DELETION_DATA)
                .UpdateDate(GetLocalDateTimeUtils.GetLocalDateTimeToStrings())
                .build();
    }

    /***
     * 添加玩家到等待房间
     * @param roomId 房间id
     * @param userId 房间用户id
     */
    private void AddPlayersWaitingRoom(String roomId, Long userId) {

        // 获取当前用户 信息
        User userInfo = userDataServiceinterface.IdGetUserInfo(userId);
//        log.info("获取当前用户 信息 {}", userInfo);

        // 转换 添加等待成员 类
        RoomMember roomMember = copyRoomsMapper.createToRoomMember(roomId, userInfo);


        // 用户阵营 必须为  BLUE(黑色),RED(红色),GAME_OVER(游戏结束or观众)
        if (!roomMemberDataServiceInterface.IsUserCampsWaitingRooms(roomId, RoomUserColorEnum.BLUE)) {
            // BLUE(黑色) 黑棋
            roomMember.setUserColor(RoomUserColorEnum.BLUE);
        } else if (!roomMemberDataServiceInterface.IsUserCampsWaitingRooms(roomId, RoomUserColorEnum.RED)) {
            // BLUE(红色) 红棋
            roomMember.setUserColor(RoomUserColorEnum.RED);
        } else {
            // GAME_OVER(游戏结束or观众)
            roomMember.setUserColor(RoomUserColorEnum.GAME_OVER);
        }

        // 成员类型（玩家或观战者），
        //    房主 ROOM_OWNER("ROOM_OWNER"),
        //    玩家 GAMER("GAMER"),
        //    观众 SPECTATOR("SPECTATOR");
        if (!roomMemberDataServiceInterface.IsUserEnumWaitingRooms(roomId, RoomUserEnum.ROOM_OWNER)) {
            // ROOM_OWNER(房主) 房主
            roomMember.setMemberType(RoomUserEnum.ROOM_OWNER);
        } else if (!roomMemberDataServiceInterface.IsUserEnumWaitingRooms(roomId, RoomUserEnum.GAMER)) {
            // GAMER(玩家) 玩家
            roomMember.setMemberType(RoomUserEnum.GAMER);
        } else {
            // SPECTATOR(观众)
            roomMember.setMemberType(RoomUserEnum.SPECTATOR);
        }

        // 添加玩家到等待房间
        if (!roomMemberDataServiceInterface.joinRoom(roomMember)) {
            throw new BusinessException(StatusCode.ERROR_CODE, "玩家加入房间失败，请联系客服！");
        }
    }


}
